﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Net;
using System.Net.Sockets;
using Debugger;
using System.IO;
using RealmMudLib.Screens;

namespace RealmMud.Protocols
{
    /// <summary>
    /// Handles the network connection to our server
    /// this is just a base and needs to be expanded
    /// Need to implement a way to display progress and errors
    /// </summary>
    public class GameClient
    {
        /// <summary>
        /// This is the Game thats asking to connect to the server
        /// </summary>
        public mainGame ThisGame { get; set; }
        /// <summary>
        /// This is what we use to connect to the server, we become a TcpClient
        /// </summary>
        public TcpClient Client { get; set; }

        /// <summary>
        /// Encryption
        /// </summary>
        public byte[] Key = null;

        public byte[] IV = null;

        /// <summary>
        /// This is our constructor for this class, we just pass the game calling us 
        /// to it
        /// </summary>
        /// <param name="game">The game that called us</param>
        public GameClient(mainGame game)
        {
            this.ThisGame = game;
        }
        /// <summary>
        /// We use this function to actually connect to the gameserver
        /// </summary>
        /// <param name="server"></param>
        public void ConnectToGameServer(IPEndPoint server)
        {
            // TODO: Load server / ip from xml ?
            // We do this inside a try/catch block so if its bad and wont connect
            // at least it wont crash us
            try
            {
                Client = new TcpClient();
                Client.Connect(server);
            }
            catch (Exception ex) { mainForm.WriteLine(ex.Message); }

            // Now check to see if we are connected to the server, if not display an error
            if (Client.Connected) 
            { 
                mainForm.WriteLine("Connected.");
                // Show our screen saying we connected !! oh joy !!
                if (!ThisGame.screenManager.AddScreen(new ConnectionAccepted("Connected!!!", ThisGame.screenManager)))
                    mainForm.WriteLine("Error adding screen");
                // Create a object to handle this
                // The server sens out a hello packet
                // As soon as we connect get it
                //We are connected successfully.
                NetworkStream networkStream = Client.GetStream();
                byte[] buffer = new byte[Client.ReceiveBufferSize];
                //Now we are connected start async read operation.
                networkStream.BeginRead(buffer, 0, buffer.Length, ReadCallback, buffer);
            }
            else 
            {
                // Show our screen saying we cant connect
                if (!ThisGame.screenManager.AddScreen(new ConnectionRefused("Server Unreachable", ThisGame.screenManager)))
                    mainForm.WriteLine("Error adding screen");
            }
        }
        /// <summary>
        /// Callback for Read operation
        /// </summary>
        /// <param name="result">The AsyncResult object</param>
        private void ReadCallback(IAsyncResult result)
        {
            int read;
            NetworkStream networkStream;
            try
            {
                networkStream = Client.GetStream();
                read = networkStream.EndRead(result);
                mainForm.WriteLine(string.Format("Read {0} bytes", read));
            }
            catch
            {
                //An error has occured when reading
                return;
            }

            if (read == 0)
            {
                //The connection has been closed.
                return;
            }

            byte[] buffer = result.AsyncState as byte[];
            byte[] actualPacket = new byte[read];
            Array.Copy(buffer, 0, actualPacket, 0, actualPacket.Length);
            //Do something with the data object here.
            mainForm.WriteLine(string.Format("Network packet Received !! {0}", Encoding.ASCII.GetString(buffer)));
            mainForm.WriteLine("\n");

            GameServer server = new GameServer(this, actualPacket);
            //Then start reading from the network again.
            networkStream.BeginRead(buffer, 0, buffer.Length, ReadCallback, buffer);
        }
    }
}
